package org.leumasjaffe.math.probability;

import java.util.Random;

import org.eclipse.jdt.annotation.NonNull;

public class UniformRV extends AbstractRV {
	private final double a;
	protected double b;
	private final boolean isDiscrete;
	
	private double range;
	
	public UniformRV(double a, double b) {
		this(new Random(), a, b);
	}
	
	public UniformRV(int a, int b) {
		this(new Random(), a, b);
	}
	
	public UniformRV(@NonNull Random r, double a, double b) {
		super(r);
		this.a = a;
		this.b = b;
		this.isDiscrete = false;
		range();
	}
	
	public UniformRV(@NonNull Random r, int a, int b) {
		super(r);
		this.a = a;
		this.b = b;
		this.isDiscrete = true;
		range();
	}
	
	boolean isDiscrete() {
		return this.isDiscrete;
	}

	@Override
	public double getEV() {
		return (this.a+this.b)/2.0;
	}

	@Override
	public double getVar() {
		if (this.isDiscrete)
			return (this.range*this.range-1)/12;
		return this.range*this.range/12;
	}

	@Override
	public double getP(double x) {
		if (x > this.a && x < this.b)
			return 1/this.range;
		return 0;
	}

	@Override
	public double calcX(double p) {
		if (!isProb(p)) throw new IllegalArgumentException("Arguement is not a valid probability");
		if (this.isDiscrete)
			return (int) (p*this.range+this.a);
		return p*this.range+this.a;
	}

	@Override
	public double getF(double x) {
		if (x <= this.a)
			return 0;
		else if (x >= this.b)
			return 1;
		else {
			if (this.isDiscrete)
				return (int) ((((int) x) - this.a + 1)/this.range);
			else
				return (x-this.a)/this.range;
		}
	}
	
	public double getF(int x) {
		return getF((double) x);
	}
	
	protected void range() {
		this.range = this.b - this.a + (isDiscrete() ? 1 : 0);
	}
	
}
